﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Diagnostics;

namespace FlightControl
{
    public partial class Plane : UserControl, IMovable
    {
        Point lastPosition;
        Point lastDrawnPosition;
        Queue<Point> Positions = new Queue<Point>();
        bool mouseIsPressed;
        Point nextPosition;
        Rect limits = new Rect(20, 50, 960, 740);

        public Plane()
        {
            
            InitializeComponent();
            _speed = 100;
            plane.MouseLeftButtonDown += new MouseButtonEventHandler(plane_MouseLeftButtonDown);
            plane.MouseLeftButtonUp += new MouseButtonEventHandler(plane_MouseLeftButtonUp);
            plane.MouseMove += new MouseEventHandler(plane_MouseMove);
            nextPosition = Position;
        }

        public void Update()
        {
            if (Position == nextPosition)
            {
                if (Positions.Count > 0)
                {
                    nextPosition = Positions.Dequeue();
                }
                else
                {
                    nextPosition = PointFor(3, 3, AngleInRad);
                    Point p1 = Position;
                    Point p2 = nextPosition;
                    double difX = (p2.X - p1.X);
                    double difY = (p2.Y - p1.Y);
                    double up = (p1.X * difY - p1.Y * difX);

                    if (nextPosition.X > limits.Right)
                    {
                        Point intermPosition = new Point(Math.Round(limits.Right),Math.Round(-((up - limits.Right * difY) / difX)));

                        nextPosition.X = 2 * limits.Right - nextPosition.X;
                        Positions.Enqueue(nextPosition);
                        if (intermPosition != Position)
                        {
                            nextPosition = intermPosition;
                        }
                    }
                    else if (nextPosition.X < limits.Left)
                    {
                        Point intermPosition = new Point(Math.Round(limits.Left), Math.Round(-((up - limits.Left * difY) / difX)));
                        nextPosition.X = limits.Left + (limits.Left - nextPosition.X);
                        Positions.Enqueue(nextPosition);
                        if (intermPosition != Position)
                        {
                            nextPosition = intermPosition;
                        }
                    }
                    else
                    {
                        nextPosition = PointFor(10,10,AngleInRad);
                    }

                }
                CreateAnimation(plane, Position, nextPosition);
            }
        }

        private Point PointFor(double distX, double distY, double angleInRad)
        {
            return new Point(Math.Round(Position.X + distX * Math.Sin(angleInRad)), Math.Round(Position.Y + distY * Math.Cos(angleInRad)));
        }

        private int _speed;
        public int Speed
        {
            get
            {
                return _speed;
            }
        }


        public double AngleInRad
        {
            get
            {
                if (Angle >= 0 && Angle <= 90) return (90-Angle+90) * (Math.PI / 180.0);
                if (Angle > 90 && Angle <= 360) return (360 + 90 - Angle+90) * (Math.PI / 180.0);
                
                return (360-Angle) * (Math.PI / 180.0)-Math.PI/2;
            }
        }
        public double Angle
        {
            get
            {
                return ((CompositeTransform)plane.RenderTransform).Rotation;
            }
            set
            {
                ((CompositeTransform)plane.RenderTransform).Rotation = value;
            }
        }

        public Point Position
        {
            get
            {
                return new Point(Canvas.GetLeft(plane), Canvas.GetTop(plane));
            }
            set
            {
                Canvas.SetLeft(plane,value.X);
                Canvas.SetTop(plane,value.Y);
                nextPosition = value;
            }
        }

        private bool _danger;
        public bool Danger
        {
            set
            {
                if (value != _danger)
                {
                    if (value)
                    {
                        VisualStateManager.GoToState(this, "DangerState", true);
                    }
                    else
                    {
                        VisualStateManager.GoToState(this, "SafeState", true);
                    }
                    _danger = value;
                }
            }
            get
            {
                return _danger;
            }
        }

        void plane_MouseMove(object sender, MouseEventArgs e)
        {
            Point position = e.GetPosition(canvas);
            if (mouseIsPressed)
            {
                Point currentPosition = new Point(Canvas.GetLeft(plane), Canvas.GetTop(plane));

                if (Math.Abs(position.X - lastDrawnPosition.X) > 10 || Math.Abs(position.Y - lastDrawnPosition.Y) > 10)
                {
                    //pathFigure.Segments.Add(new QuadraticBezierSegment() { Point2 = position, Point1 = position });
                    pathFigure.Segments.Add(new LineSegment() { Point = position });
                    Positions.Enqueue(position);
                    lastDrawnPosition = position;
                }
                lastPosition = position;
            }
        }

        void plane_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            plane.ReleaseMouseCapture();
            mouseIsPressed = false;
        }

        void plane_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            plane.CaptureMouse();
            Point position = e.GetPosition(canvas);
            mouseIsPressed = true;

            Positions.Clear();

            Point currentPosition = new Point(Canvas.GetLeft(plane), Canvas.GetTop(plane));

            lastPosition = position;

            lastDrawnPosition = position;
            pathFigure.Segments.Clear();
            pathFigure.StartPoint = lastDrawnPosition;
        }

        private Queue<Tuple<string, Storyboard>> storyboards = new Queue<Tuple<string, Storyboard>>();
        private void CreateAnimation(UIElement theObject, Point oldPosition, Point newPosition)
        {

            Storyboard sb = new Storyboard();
            sb.Completed += new EventHandler(sb_Completed);

            double angle = GetAngle(newPosition, oldPosition);
            Debug.WriteLine(oldPosition.ToString());
            Debug.WriteLine(newPosition.ToString());

            double distance = Math.Sqrt(Math.Pow((oldPosition.X - newPosition.X), 2) + Math.Pow((oldPosition.Y - newPosition.Y), 2));
            Debug.WriteLine(distance);
            double time = distance / _speed;


            double currentAngle = (theObject.RenderTransform as CompositeTransform).Rotation;
            if (angle < 0)
            {
                angle = 360 + angle;
            }

            if (Math.Abs(currentAngle - angle) > 180)
            {
                double minus = currentAngle > angle ? -1 : 1;
                (theObject.RenderTransform as CompositeTransform).Rotation = minus * (360 + minus * currentAngle);
            }


            DoubleAnimation positionXAnimation = new DoubleAnimation() { Duration = new Duration(TimeSpan.FromSeconds(time)) };
            DoubleAnimation positionYAnimation = new DoubleAnimation() { Duration = new Duration(TimeSpan.FromSeconds(time)) };
            DoubleAnimation angleAnimation = new DoubleAnimation() { Duration = new Duration(TimeSpan.FromSeconds(0.5)) };
            angleAnimation.EasingFunction = new CubicEase();

            Storyboard.SetTarget(positionXAnimation, theObject);
            Storyboard.SetTarget(positionYAnimation, theObject);
            Storyboard.SetTarget(angleAnimation, theObject);
            Storyboard.SetTargetProperty(positionXAnimation, new PropertyPath("(Canvas.Left)"));
            Storyboard.SetTargetProperty(positionYAnimation, new PropertyPath("(Canvas.Top)"));
            Storyboard.SetTargetProperty(angleAnimation, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.Rotation)"));

            //positionXAnimation.From = oldPosition.X;
            //positionYAnimation.From = oldPosition.Y;
            positionXAnimation.To = newPosition.X;
            positionYAnimation.To = newPosition.Y;
            angleAnimation.To = angle;

            sb.Children.Add(positionXAnimation);
            sb.Children.Add(positionYAnimation);
            sb.Children.Add(angleAnimation);

            string id = Guid.NewGuid().ToString();
            canvas.Resources.Add(id, sb);
            storyboards.Enqueue(Tuple.Create(id, sb));
            sb.Begin();
        }

        void sb_Completed(object sender, EventArgs e)
        {
            canvas.Resources.Remove(storyboards.Dequeue().Item1);
        }

        public double GetAngle(Point position, Point fromPosition)
        {

            double m = (position.X - fromPosition.X) / (position.Y - fromPosition.Y);
            double angleInRad = Math.Atan(m);
            double angleInDegrees = 0;
            if (position.X > fromPosition.X)
            {
                if (position.Y > fromPosition.Y)
                {
                    //cadran IV
                    angleInDegrees = (Math.PI - angleInRad) * (double)180 / Math.PI;

                }
                else if (position.Y < fromPosition.Y)
                {
                    //cadran I
                    angleInDegrees = (Math.PI - angleInRad) * (double)180 / Math.PI - 180;
                }
                else
                {
                    //intre cadranele I si IV pe axa Y
                    angleInDegrees = 90;
                }
            }
            else if (position.X < fromPosition.X)
            {
                if (position.Y > fromPosition.Y)
                {
                    //cadran  III
                    angleInDegrees = (Math.PI - angleInRad) * (double)180 / Math.PI;
                }
                else if (position.Y < fromPosition.Y)
                {
                    //cadran II
                    angleInDegrees = (Math.PI - angleInRad) * (double)180 / Math.PI - 180;
                }
                else
                {
                    //intre cadranele II si III pe axa Y
                    angleInDegrees = 270;

                }
            }
            else
            {

                if (position.Y > fromPosition.Y)
                {
                    //intre cadranele III si IV
                    angleInDegrees = 180;

                }
                else if (position.Y < fromPosition.Y)
                {
                    //intre cadranele I si II
                    angleInDegrees = 0;
                }
                else
                {
                    //in 0

                }
            }

            return angleInDegrees;
        }


    }
}
